pub mod err;

use lazy_static::lazy_static;
use std::sync::Mutex;

lazy_static! {
    // Mutex 互斥锁,常用于多线程之间的数据共享
    // 一般通过rc或者arc来实现引用计数,完成线程之间的所有权共享
    static ref LOG_LK: Mutex<u64> = Mutex::new(0);
}

// #[macro_export] attr表示这个宏定义可以在外部cargo中使用,类似于全局定义
#[macro_export]
macro_rules! map {
    () => {{
        std::collections::HashMap::new()
    }};
    (B)=>{{
        std::collections::BTreeMap::new()
    }};
    ($(||)+)=>{{
        std::collections::HashMap::new
    }};
    (B$(||)+)=>{{
        std::collections::BTreeMap::new
    }};
    ($($k:expr => $v:expr),*)=>{{
        let mut m = std::collections::HashMap::with_capacity([$(&$k),*].len());
        $(m.insert($k,$v);)*
        m
    }};

    (B $($k:expr => $v:expr),*)=>{{
        let mut m = map!(B);
        $(m.insert($k,$v);)*
        m
    }}

}

#[macro_export]
macro_rules! vct {
    () => {
        Vec::new()
    };
    ($(||)+)=>{
        Vec::new
    };
    ($($v:expr),*)=>{{
        vec![$($v),*]
    }};
    ( $v:expr ; $n: expr )=>{{
        vec![$v;$n]
    }}
}





#[cfg(test)]
mod tests {
    #![allow(non_snake_case)]

    use std::collections::{HashMap, BTreeMap};

    #[test]
    fn vct_test() {
        let mut vec: Vec<i32> = vct!();
        vec.push(1);
        assert_eq!(vec.pop(), Some(1));
        let x: Vec<i32> = vct!(||)();
        assert_eq!(x.len(), 0);
        let vec1 = vct!(1,2,3,4,5,6,7,8);
        assert_eq!(vec1.len(), 8);
        let vec2 = vct![5; 2];
        assert_eq!(vec2.get(1), Some(&5));
    }


    #[test]
    fn map_test() {
        let hash_map: HashMap<u32, u32> = map!();
        assert_eq!(hash_map.len(), 0);
        let tree_map: BTreeMap<u32, u32> = map!(B);
        assert_eq!(tree_map.len(), 0);

        let mut hash_map_a: HashMap<u32, u32> = map!(||)();
        let key: u32 = 45;
        let value: u32 = 23;
        hash_map_a.insert(key, value);
        assert_eq!(hash_map_a.get(&key), Some(&value));

        let mut b_tree_map = map!(B||)();
        b_tree_map.insert(key, value);
        assert_eq!(b_tree_map.get(&key), Some(&value));

        let map1 = map!(1=>2,2=>4);
        assert_eq!(map1.get(&1), Some(&2));

        let map2 = map!(B 1=>2,2=>4);
        assert_eq!(map2.get(&2), Some(&4));

        for (x, (k, v)) in map2.into_iter().enumerate() {
            assert_eq!(1 + x, k);
            assert_eq!(2 * k, v);
        }
    }
}


